using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CKY.AgentPlatform.ModelConfigs
{
    /// <summary>
    /// 错误类型枚举
    /// </summary>
    public enum ModelErrorType
    {
        /// <summary>
        /// 配置错误
        /// </summary>
        ConfigurationError = 0,

        /// <summary>
        /// 网络错误
        /// </summary>
        NetworkError = 1,

        /// <summary>
        /// 认证错误
        /// </summary>
        AuthenticationError = 2,

        /// <summary>
        /// 授权错误
        /// </summary>
        AuthorizationError = 3,

        /// <summary>
        /// 速率限制错误
        /// </summary>
        RateLimitError = 4,

        /// <summary>
        /// 配额不足错误
        /// </summary>
        QuotaExceededError = 5,

        /// <summary>
        /// 模型不可用错误
        /// </summary>
        ModelUnavailableError = 6,

        /// <summary>
        /// 超时错误
        /// </summary>
        TimeoutError = 7,

        /// <summary>
        /// 内容过滤错误
        /// </summary>
        ContentFilterError = 8,

        /// <summary>
        /// 参数验证错误
        /// </summary>
        ParameterValidationError = 9,

        /// <summary>
        /// 响应解析错误
        /// </summary>
        ResponseParseError = 10,

        /// <summary>
        /// 适配器错误
        /// </summary>
        AdapterError = 11,

        /// <summary>
        /// 未知错误
        /// </summary>
        UnknownError = 99
    }

    /// <summary>
    /// 错误严重程度
    /// </summary>
    public enum ErrorSeverity
    {
        /// <summary>
        /// 信息级别
        /// </summary>
        Info = 0,

        /// <summary>
        /// 警告级别
        /// </summary>
        Warning = 1,

        /// <summary>
        /// 错误级别
        /// </summary>
        Error = 2,

        /// <summary>
        /// 严重错误级别
        /// </summary>
        Critical = 3
    }

    /// <summary>
    /// 错误恢复策略
    /// </summary>
    public enum ErrorRecoveryStrategy
    {
        /// <summary>
        /// 立即重试
        /// </summary>
        ImmediateRetry = 0,

        /// <summary>
        /// 延迟重试
        /// </summary>
        DelayedRetry = 1,

        /// <summary>
        /// 指数退避重试
        /// </summary>
        ExponentialBackoff = 2,

        /// <summary>
        /// 切换适配器
        /// </summary>
        SwitchAdapter = 3,

        /// <summary>
        /// 降级处理
        /// </summary>
        Fallback = 4,

        /// <summary>
        /// 直接失败
        /// </summary>
        FailFast = 5
    }

    /// <summary>
    /// 模型错误信息
    /// </summary>
    public class ModelErrorInfo
    {
        /// <summary>
        /// 错误类型
        /// </summary>
        public ModelErrorType ErrorType { get; set; }

        /// <summary>
        /// 错误代码
        /// </summary>
        public string ErrorCode { get; set; }

        /// <summary>
        /// 错误消息
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// 错误严重程度
        /// </summary>
        public ErrorSeverity Severity { get; set; }

        /// <summary>
        /// 恢复策略
        /// </summary>
        public ErrorRecoveryStrategy RecoveryStrategy { get; set; }

        /// <summary>
        /// 建议的重试次数
        /// </summary>
        public int SuggestedRetryCount { get; set; }

        /// <summary>
        /// 建议的延迟时间（毫秒）
        /// </summary>
        public int SuggestedDelayMs { get; set; }

        /// <summary>
        /// 错误详情
        /// </summary>
        public Dictionary<string, object> Details { get; set; } = new();

        /// <summary>
        /// 原始异常
        /// </summary>
        public Exception OriginalException { get; set; }

        /// <summary>
        /// 发生时间
        /// </summary>
        public DateTime OccurredAt { get; set; } = DateTime.UtcNow;

        /// <summary>
        /// 是否可以重试
        /// </summary>
        public bool CanRetry => RecoveryStrategy != ErrorRecoveryStrategy.FailFast;

        /// <summary>
        /// 是否需要用户干预
        /// </summary>
        public bool RequiresUserIntervention => ErrorType == ModelErrorType.AuthenticationError ||
                                               ErrorType == ModelErrorType.QuotaExceededError ||
                                               ErrorType == ModelErrorType.ConfigurationError;
    }

    /// <summary>
    /// 错误分类器
    /// </summary>
    public static class ModelErrorClassifier
    {
        /// <summary>
        /// 分类异常
        /// </summary>
        /// <param name="exception">异常</param>
        /// <param name="context">上下文信息</param>
        /// <returns>错误信息</returns>
        public static ModelErrorInfo ClassifyException(Exception exception, Dictionary<string, object> context = null)
        {
            var errorInfo = new ModelErrorInfo
            {
                OriginalException = exception,
                Details = context ?? new Dictionary<string, object>()
            };

            switch (exception)
            {
                case InvalidOperationException invalidOpEx:
                    return ClassifyInvalidOperationException(invalidOpEx, errorInfo);

                case TimeoutException timeoutEx:
                    return ClassifyTimeoutException(timeoutEx, errorInfo);

                case System.Net.Http.HttpRequestException httpEx:
                    return ClassifyHttpRequestException(httpEx, errorInfo);

                case System.Text.Json.JsonException jsonEx:
                    return ClassifyJsonException(jsonEx, errorInfo);

                case UnauthorizedAccessException authEx:
                    return ClassifyUnauthorizedAccessException(authEx, errorInfo);

                case System.Net.Sockets.SocketException socketEx:
                    return ClassifySocketException(socketEx, errorInfo);

                case TaskCanceledException taskCanceledEx:
                    return ClassifyTaskCanceledException(taskCanceledEx, errorInfo);

                default:
                    return ClassifyGenericException(exception, errorInfo);
            }
        }

        private static ModelErrorInfo ClassifyInvalidOperationException(InvalidOperationException ex, ModelErrorInfo errorInfo)
        {
            var message = ex.Message?.ToLower() ?? "";

            if (message.Contains("配置无效") || message.Contains("configuration"))
            {
                errorInfo.ErrorType = ModelErrorType.ConfigurationError;
                errorInfo.Severity = ErrorSeverity.Error;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                errorInfo.ErrorCode = "CONFIG_INVALID";
                errorInfo.ErrorMessage = "模型配置无效";
            }
            else if (message.Contains("不支持") || message.Contains("not supported"))
            {
                errorInfo.ErrorType = ModelErrorType.ParameterValidationError;
                errorInfo.Severity = ErrorSeverity.Error;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                errorInfo.ErrorCode = "PARAMETER_NOT_SUPPORTED";
                errorInfo.ErrorMessage = "不支持的参数或功能";
            }
            else
            {
                errorInfo.ErrorType = ModelErrorType.UnknownError;
                errorInfo.Severity = ErrorSeverity.Error;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                errorInfo.ErrorCode = "INVALID_OPERATION";
                errorInfo.ErrorMessage = "操作无效";
            }

            return errorInfo;
        }

        private static ModelErrorInfo ClassifyTimeoutException(TimeoutException ex, ModelErrorInfo errorInfo)
        {
            errorInfo.ErrorType = ModelErrorType.TimeoutError;
            errorInfo.Severity = ErrorSeverity.Warning;
            errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
            errorInfo.ErrorCode = "TIMEOUT";
            errorInfo.ErrorMessage = "请求超时";
            errorInfo.SuggestedRetryCount = 2;
            errorInfo.SuggestedDelayMs = 1000;

            return errorInfo;
        }

        private static ModelErrorInfo ClassifyHttpRequestException(System.Net.Http.HttpRequestException ex, ModelErrorInfo errorInfo)
        {
            var message = ex.Message?.ToLower() ?? "";

            if (message.Contains("connection") || message.Contains("network"))
            {
                errorInfo.ErrorType = ModelErrorType.NetworkError;
                errorInfo.Severity = ErrorSeverity.Warning;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.ExponentialBackoff;
                errorInfo.ErrorCode = "NETWORK_ERROR";
                errorInfo.ErrorMessage = "网络连接错误";
                errorInfo.SuggestedRetryCount = 3;
                errorInfo.SuggestedDelayMs = 2000;
            }
            else if (message.Contains("401") || message.Contains("unauthorized"))
            {
                errorInfo.ErrorType = ModelErrorType.AuthenticationError;
                errorInfo.Severity = ErrorSeverity.Critical;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                errorInfo.ErrorCode = "AUTH_FAILED";
                errorInfo.ErrorMessage = "认证失败";
            }
            else if (message.Contains("403") || message.Contains("forbidden"))
            {
                errorInfo.ErrorType = ModelErrorType.AuthorizationError;
                errorInfo.Severity = ErrorSeverity.Error;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                errorInfo.ErrorCode = "AUTH_FORBIDDEN";
                errorInfo.ErrorMessage = "访问被禁止";
            }
            else if (message.Contains("429") || message.Contains("too many requests"))
            {
                errorInfo.ErrorType = ModelErrorType.RateLimitError;
                errorInfo.Severity = ErrorSeverity.Warning;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
                errorInfo.ErrorCode = "RATE_LIMIT";
                errorInfo.ErrorMessage = "请求频率超限";
                errorInfo.SuggestedRetryCount = 3;
                errorInfo.SuggestedDelayMs = 5000;
            }
            else
            {
                errorInfo.ErrorType = ModelErrorType.NetworkError;
                errorInfo.Severity = ErrorSeverity.Warning;
                errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
                errorInfo.ErrorCode = "HTTP_REQUEST_FAILED";
                errorInfo.ErrorMessage = "HTTP请求失败";
                errorInfo.SuggestedRetryCount = 2;
                errorInfo.SuggestedDelayMs = 1000;
            }

            return errorInfo;
        }

        public static ModelErrorInfo ClassifyJsonException(System.Text.Json.JsonException ex, ModelErrorInfo errorInfo)
        {
            errorInfo.ErrorType = ModelErrorType.ResponseParseError;
            errorInfo.Severity = ErrorSeverity.Error;
            errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
            errorInfo.ErrorCode = "JSON_PARSE_ERROR";
            errorInfo.ErrorMessage = "JSON解析失败";

            return errorInfo;
        }

        private static ModelErrorInfo ClassifyUnauthorizedAccessException(UnauthorizedAccessException ex, ModelErrorInfo errorInfo)
        {
            errorInfo.ErrorType = ModelErrorType.AuthenticationError;
            errorInfo.Severity = ErrorSeverity.Critical;
            errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
            errorInfo.ErrorCode = "UNAUTHORIZED";
            errorInfo.ErrorMessage = "未授权访问";

            return errorInfo;
        }

        private static ModelErrorInfo ClassifySocketException(System.Net.Sockets.SocketException ex, ModelErrorInfo errorInfo)
        {
            errorInfo.ErrorType = ModelErrorType.NetworkError;
            errorInfo.Severity = ErrorSeverity.Warning;
            errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.ExponentialBackoff;
            errorInfo.ErrorCode = "SOCKET_ERROR";
            errorInfo.ErrorMessage = "网络套接字错误";
            errorInfo.SuggestedRetryCount = 3;
            errorInfo.SuggestedDelayMs = 3000;

            return errorInfo;
        }

        private static ModelErrorInfo ClassifyTaskCanceledException(TaskCanceledException ex, ModelErrorInfo errorInfo)
        {
            if (ex.InnerException is TimeoutException)
            {
                return ClassifyTimeoutException((TimeoutException)ex.InnerException, errorInfo);
            }

            errorInfo.ErrorType = ModelErrorType.TimeoutError;
            errorInfo.Severity = ErrorSeverity.Warning;
            errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
            errorInfo.ErrorCode = "TASK_CANCELLED";
            errorInfo.ErrorMessage = "任务被取消";
            errorInfo.SuggestedRetryCount = 1;
            errorInfo.SuggestedDelayMs = 1000;

            return errorInfo;
        }

        private static ModelErrorInfo ClassifyGenericException(Exception ex, ModelErrorInfo errorInfo)
        {
            errorInfo.ErrorType = ModelErrorType.UnknownError;
            errorInfo.Severity = ErrorSeverity.Error;
            errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
            errorInfo.ErrorCode = "UNKNOWN_ERROR";
            errorInfo.ErrorMessage = "未知错误";

            return errorInfo;
        }

        /// <summary>
        /// 从HTTP状态码分类错误
        /// </summary>
        /// <param name="statusCode">HTTP状态码</param>
        /// <param name="responseContent">响应内容</param>
        /// <returns>错误信息</returns>
        public static ModelErrorInfo ClassifyHttpError(System.Net.HttpStatusCode statusCode, string responseContent = null)
        {
            var errorInfo = new ModelErrorInfo();

            switch (statusCode)
            {
                case System.Net.HttpStatusCode.BadRequest:
                    errorInfo.ErrorType = ModelErrorType.ParameterValidationError;
                    errorInfo.Severity = ErrorSeverity.Error;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                    errorInfo.ErrorCode = "BAD_REQUEST";
                    errorInfo.ErrorMessage = "请求参数错误";
                    break;

                case System.Net.HttpStatusCode.Unauthorized:
                    errorInfo.ErrorType = ModelErrorType.AuthenticationError;
                    errorInfo.Severity = ErrorSeverity.Critical;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                    errorInfo.ErrorCode = "UNAUTHORIZED";
                    errorInfo.ErrorMessage = "认证失败";
                    break;

                case System.Net.HttpStatusCode.Forbidden:
                    errorInfo.ErrorType = ModelErrorType.AuthorizationError;
                    errorInfo.Severity = ErrorSeverity.Error;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                    errorInfo.ErrorCode = "FORBIDDEN";
                    errorInfo.ErrorMessage = "访问被禁止";
                    break;

                case System.Net.HttpStatusCode.NotFound:
                    errorInfo.ErrorType = ModelErrorType.ModelUnavailableError;
                    errorInfo.Severity = ErrorSeverity.Error;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.SwitchAdapter;
                    errorInfo.ErrorCode = "NOT_FOUND";
                    errorInfo.ErrorMessage = "模型或服务不可用";
                    break;

                case System.Net.HttpStatusCode.TooManyRequests:
                    errorInfo.ErrorType = ModelErrorType.RateLimitError;
                    errorInfo.Severity = ErrorSeverity.Warning;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
                    errorInfo.ErrorCode = "RATE_LIMITED";
                    errorInfo.ErrorMessage = "请求频率超限";
                    errorInfo.SuggestedRetryCount = 3;
                    errorInfo.SuggestedDelayMs = 5000;
                    break;

                case System.Net.HttpStatusCode.InternalServerError:
                    errorInfo.ErrorType = ModelErrorType.ModelUnavailableError;
                    errorInfo.Severity = ErrorSeverity.Error;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
                    errorInfo.ErrorCode = "SERVER_ERROR";
                    errorInfo.ErrorMessage = "服务器内部错误";
                    errorInfo.SuggestedRetryCount = 2;
                    errorInfo.SuggestedDelayMs = 2000;
                    break;

                case System.Net.HttpStatusCode.BadGateway:
                case System.Net.HttpStatusCode.ServiceUnavailable:
                case System.Net.HttpStatusCode.GatewayTimeout:
                    errorInfo.ErrorType = ModelErrorType.ModelUnavailableError;
                    errorInfo.Severity = ErrorSeverity.Warning;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.DelayedRetry;
                    errorInfo.ErrorCode = "SERVICE_UNAVAILABLE";
                    errorInfo.ErrorMessage = "服务暂时不可用";
                    errorInfo.SuggestedRetryCount = 3;
                    errorInfo.SuggestedDelayMs = 3000;
                    break;

                default:
                    errorInfo.ErrorType = ModelErrorType.UnknownError;
                    errorInfo.Severity = ErrorSeverity.Error;
                    errorInfo.RecoveryStrategy = ErrorRecoveryStrategy.FailFast;
                    errorInfo.ErrorCode = $"HTTP_{(int)statusCode}";
                    errorInfo.ErrorMessage = $"HTTP错误: {statusCode}";
                    break;
            }

            // 尝试从响应内容中提取更详细的错误信息
            if (!string.IsNullOrWhiteSpace(responseContent))
            {
                errorInfo.Details["ResponseContent"] = responseContent;

                // 尝试解析JSON响应中的错误信息
                try
                {
                    using var jsonDoc = System.Text.Json.JsonDocument.Parse(responseContent);
                    var root = jsonDoc.RootElement;

                    if (root.TryGetProperty("error", out var errorElement))
                    {
                        if (errorElement.TryGetProperty("message", out var messageElement))
                        {
                            errorInfo.ErrorMessage = messageElement.GetString() ?? errorInfo.ErrorMessage;
                        }
                        if (errorElement.TryGetProperty("type", out var typeElement))
                        {
                            errorInfo.Details["ErrorType"] = typeElement.GetString();
                        }
                        if (errorElement.TryGetProperty("code", out var codeElement))
                        {
                            errorInfo.Details["ErrorCode"] = codeElement.GetString();
                        }
                    }
                }
                catch
                {
                    // 忽略JSON解析错误
                }
            }

            return errorInfo;
        }
    }
}